home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / util / lev_main.c < prev    next >
C/C++ Source or Header  |  1992-12-30  |  31KB  |  1,389 lines

  1. /*    SCCS Id: @(#)lev_main.c    3.1    92/12/11    */
  2. /*    Copyright (c) 1989 by Jean-Christophe Collet */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * This file contains the main function for the parser
  7.  * and some useful functions needed by yacc
  8.  */
  9.  
  10. #include "hack.h"
  11. #include "sp_lev.h"
  12. #ifdef STRICT_REF_DEF
  13. #include "termcap.h"
  14. #endif
  15.  
  16. #ifdef MAC
  17. # ifdef applec
  18. #  define MPWTOOL
  19. #  include <CursorCtl.h>
  20. # endif
  21. #endif
  22.  
  23. #ifndef MPWTOOL
  24. # define SpinCursor(x)
  25. #endif
  26.  
  27. #ifndef O_WRONLY
  28. # include <fcntl.h>
  29. #endif
  30. #ifndef O_CREAT    /* some older BSD systems do not define O_CREAT in <fcntl.h> */
  31. # include <sys/file.h>
  32. #endif
  33. #ifndef O_BINARY    /* used for micros, no-op for others */
  34. # define O_BINARY 0
  35. #endif
  36.  
  37. #define NEWLINE    10    /* under Mac MPW C '\n' is 13 so don't use it. */
  38.  
  39. #define ERR        (-1)
  40.  
  41. #define NewTab(type, size)    (type **) alloc(sizeof(type *) * size)
  42. #define Free(ptr)        if(ptr) free((genericptr_t) (ptr))
  43. #define Write(fd, item, size)    (void) write(fd, (genericptr_t)(item), size)
  44.  
  45. #ifdef MICRO
  46. # undef exit
  47. # ifndef AMIGA
  48. extern void FDECL(exit, (int));
  49. # endif
  50. #endif
  51.  
  52. #define MAX_ERRORS    25
  53.  
  54. extern int  NDECL (yyparse);
  55. extern void FDECL (init_yyin, (FILE *));
  56. extern void FDECL (init_yyout, (FILE *));
  57.  
  58. int  FDECL (main, (int, char **));
  59. void FDECL (yyerror, (char *));
  60. void FDECL (yywarning, (char *));
  61. int  NDECL (yywrap);
  62. char *FDECL(dup_string,(const char *));
  63. int FDECL(get_floor_type, (CHAR_P));
  64. int FDECL(get_room_type, (char *));
  65. int FDECL(get_trap_type, (char *));
  66. int FDECL(get_monster_id, (char *, CHAR_P));
  67. int FDECL(get_object_id, (char *));
  68. boolean FDECL(check_monster_char, (CHAR_P));
  69. boolean FDECL(check_object_char, (CHAR_P));
  70. char FDECL(what_map_char, (CHAR_P));
  71. void FDECL(scan_map, (char *));
  72. void NDECL(wallify_map);
  73. boolean NDECL(check_subrooms);
  74. void FDECL(check_coord, (int, int, char *));
  75. void NDECL(store_part);
  76. void NDECL(store_room);
  77. static void FDECL(write_common_data, (int,int,lev_init *,long));
  78. void FDECL(write_maze, (int, specialmaze *));
  79. void FDECL(write_lev, (int, splev *));
  80. void FDECL(free_rooms, (room **, int));
  81.  
  82. static struct {
  83.     const char *name;
  84.     short type;
  85. } trap_types[TRAPNUM] = {
  86.     { "arrow",    ARROW_TRAP },
  87.     { "dart",    DART_TRAP },
  88.     { "falling rock", ROCKTRAP },
  89.     { "board",    SQKY_BOARD },
  90.     { "bear",    BEAR_TRAP },
  91.     { "land mine",    LANDMINE },
  92.     { "sleep gas",    SLP_GAS_TRAP },
  93.     { "rust",    RUST_TRAP },
  94.     { "fire",    FIRE_TRAP },
  95.     { "pit",    PIT },
  96.     { "spiked pit",    SPIKED_PIT },
  97.     { "trapdoor",    TRAPDOOR },
  98.     { "teleport",    TELEP_TRAP },
  99.     { "level teleport", LEVEL_TELEP },
  100.     { "magic portal",   MAGIC_PORTAL },
  101.     { "web",    WEB },
  102.     { "statue",    STATUE_TRAP },
  103.     { "magic",    MAGIC_TRAP },
  104.     { "anti magic",    ANTI_MAGIC },
  105. #ifdef POLYSELF
  106.     { "polymorph",    POLY_TRAP },
  107. #endif
  108.     { 0, 0 }
  109. };
  110.  
  111. static struct {
  112.     char *name;
  113.     int type;
  114. } room_types[] = {
  115.     /* for historical reasons, room types are not contiguous numbers */
  116.     /* (type 1 is skipped) */
  117.     { "ordinary",     OROOM },
  118.     { "throne",     COURT },
  119.     { "swamp",     SWAMP },
  120.     { "vault",     VAULT },
  121.     { "beehive",     BEEHIVE },
  122.     { "morgue",     MORGUE },
  123. #ifdef ARMY
  124.     { "barracks",     BARRACKS },
  125. #endif
  126.     { "zoo",     ZOO },
  127.     { "delphi",     DELPHI },
  128.     { "temple",     TEMPLE },
  129.     { "shop",     SHOPBASE },
  130.     { "armor shop",     ARMORSHOP },
  131.     { "scroll shop", SCROLLSHOP },
  132.     { "potion shop", POTIONSHOP },
  133.     { "weapon shop", WEAPONSHOP },
  134.     { "food shop",     FOODSHOP },
  135.     { "ring shop",     RINGSHOP },
  136.     { "wand shop",     WANDSHOP },
  137.     { "tool shop",     TOOLSHOP },
  138.     { "book shop",     BOOKSHOP },
  139.     { "candle shop", CANDLESHOP },
  140.     { 0, 0 }
  141. };
  142.  
  143. char *fname = "(stdin)";
  144. int fatal_error = 0;
  145. int want_warnings = 0;
  146.  
  147. /* Flex 2.3 bug work around */
  148. int yy_more_len = 0;
  149.  
  150. extern char tmpmessage[];
  151. extern altar *tmpaltar[];
  152. extern lad *tmplad[];
  153. extern stair *tmpstair[];
  154. extern digpos *tmpdig[];
  155. extern char *tmpmap[];
  156. extern region *tmpreg[];
  157. extern lev_region *tmplreg[];
  158. extern door *tmpdoor[];
  159. extern room_door *tmprdoor[];
  160. extern trap *tmptrap[];
  161. extern monster *tmpmonst[];
  162. extern object *tmpobj[];
  163. extern drawbridge *tmpdb[];
  164. extern walk *tmpwalk[];
  165. extern gold *tmpgold[];
  166. extern fountain *tmpfountain[];
  167. extern sink *tmpsink[];
  168. extern pool *tmppool[];
  169. extern engraving *tmpengraving[];
  170. extern mazepart *tmppart[];
  171. extern room *tmproom[];
  172. extern corridor *tmpcor[];
  173.  
  174. extern int n_olist, n_mlist, n_plist;
  175.  
  176. extern unsigned int nlreg, nreg, ndoor, ntrap, nmons, nobj;
  177. extern unsigned int ndb, nwalk, npart, ndig, nlad, nstair;
  178. extern unsigned int naltar, ncorridor, nrooms, ngold, nengraving;
  179. extern unsigned int nfountain, npool, nsink;
  180.  
  181. extern unsigned int max_x_map, max_y_map;
  182.  
  183. extern int line_number, colon_line_number;
  184.  
  185. int
  186. main(argc, argv)
  187. int argc;
  188. char **argv;
  189. {
  190.     FILE *fin;
  191.     int i;
  192. #ifdef MAC_THINKC5
  193.     static char *mac_argv[] = {    "lev_comp",    /* dummy argv[0] */
  194.                 ":dat:Arch.des",
  195.                 ":dat:Barb.des",
  196.                 ":dat:Caveman.des",
  197.                 ":dat:Elf.des",
  198.                 ":dat:Healer.des",
  199.                 ":dat:Knight.des",
  200.                 ":dat:Priest.des",
  201.                 ":dat:Rogue.des",
  202.                 ":dat:Samurai.des",
  203.                 ":dat:Tourist.des",
  204.                 ":dat:Valkyrie.des",
  205.                 ":dat:Wizard.des",
  206.                 ":dat:bigroom.des",
  207.                 ":dat:castle.des",
  208.                 ":dat:endgame.des",
  209.                 ":dat:gehennom.des",
  210.                 ":dat:knox.des",
  211.                 ":dat:medusa.des",
  212.                 ":dat:mines.des",
  213.                 ":dat:oracle.des",
  214.                 ":dat:tower.des",
  215.                 ":dat:yendor.des"
  216.                 };
  217.  
  218.     argc = SIZE(mac_argv);
  219.     argv = mac_argv;
  220. #endif
  221.     /* Note:  these initializers don't do anything except guarantee that
  222.         we're linked properly.
  223.     */
  224.     monst_init();
  225.     objects_init();
  226.     decl_init();
  227.  
  228.     init_yyout(stdout);
  229.     if (argc == 1) {        /* Read standard input */
  230.         init_yyin(stdin);
  231.         yyparse();
  232.     } else {            /* Otherwise every argument is a filename */
  233.         for(i=1; i<argc; i++) {
  234.             fname = argv[i];
  235.             if(!strcmp(fname, "-w")) {
  236.             want_warnings++;
  237.             continue;
  238.             }
  239.             fin = freopen(fname, "r", stdin);
  240.             if (!fin) {
  241.             (void) fprintf(stderr,"Can't open \"%s\" for input.\n",
  242.                         fname);
  243.             perror(fname);
  244.             } else {
  245.             init_yyin(fin);
  246.             yyparse();
  247.             }
  248.             line_number = 1;
  249.             fatal_error = 0;
  250.         }
  251.     }
  252. #ifndef VMS
  253.     return 0;
  254. #else
  255.     return 1;       /* vms success */
  256. #endif /*VMS*/
  257. }
  258.  
  259. /*
  260.  * Each time the parser detects an error, it uses this function.
  261.  * Here we take count of the errors. To continue farther than
  262.  * MAX_ERRORS wouldn't be reasonable.
  263.  * Assume that explicit calls from lev_comp.y have the 1st letter
  264.  * capitalized, to allow printing of the line containing the start of
  265.  * the current declaration, instead of the beginning of the next declaration.
  266.  */
  267.  
  268. void
  269. yyerror(s)
  270. char *s;
  271. {
  272.     (void) fprintf(stderr, "%s: line %d : %s\n", fname,
  273.         (*s >= 'A' && *s <= 'Z') ? colon_line_number : line_number, s);
  274.     if (++fatal_error > MAX_ERRORS) {
  275.         (void) fprintf(stderr,"Too many errors, good bye!\n");
  276.         exit(1);
  277.     }
  278. }
  279.  
  280. /*
  281.  * Just display a warning (that is : a non fatal error)
  282.  */
  283.  
  284. void
  285. yywarning(s)
  286. char *s;
  287. {
  288.     (void) fprintf(stderr, "%s: line %d : WARNING : %s\n",
  289.                 fname, colon_line_number, s);
  290. }
  291.  
  292. int
  293. yywrap()
  294. {
  295.     return 1;
  296. }
  297.  
  298. /*
  299.  * Duplicate a string.
  300.  */
  301.  
  302. char *
  303. dup_string(s)
  304. const char *s;
  305. {
  306.     char *news;
  307.  
  308.     if (!s)
  309.         return (char *) 0;
  310.     news = (char *) alloc(strlen(s)+1);
  311.     Strcpy(news, s);
  312.     return news;
  313. }
  314.  
  315. /*
  316.  * Find the type of floor, knowing its char representation.
  317.  */
  318.  
  319. int
  320. get_floor_type(c)
  321. char c;
  322. {
  323.     int val;
  324.  
  325.     SpinCursor(3);
  326.     val = what_map_char(c);
  327.     if(val == INVALID_TYPE) {
  328.         val = ERR;
  329.         yywarning("Invalid fill character in MAZE declaration");
  330.     }
  331.     return val;
  332. }
  333.  
  334. /*
  335.  * Find the type of a room in the table, knowing its name.
  336.  */
  337.  
  338. int
  339. get_room_type(s)
  340. char *s;
  341. {
  342.     register int i;
  343.  
  344.     SpinCursor(3);
  345.     for(i=0; room_types[i].name; i++)
  346.         if (!strcmp(s, room_types[i].name))
  347.         return ((int) room_types[i].type);
  348.     return ERR;
  349. }
  350.  
  351. /*
  352.  * Find the type of a trap in the table, knowing its name.
  353.  */
  354.  
  355. int
  356. get_trap_type(s)
  357. char *s;
  358. {
  359.     register int i;
  360.  
  361.     SpinCursor(3);
  362.     for(i=0; i < TRAPNUM - 1; i++)
  363.         if(!strcmp(s,trap_types[i].name))
  364.         return((int)trap_types[i].type);
  365.     return ERR;
  366. }
  367.  
  368. /*
  369.  * Find the index of a monster in the table, knowing its name.
  370.  */
  371. int
  372. get_monster_id(s, c)
  373. char *s;
  374. char c;
  375. {
  376.     register int i, class;
  377.  
  378.     SpinCursor(3);
  379.     class = def_char_to_monclass(c);
  380.     if (c && class == MAXMCLASSES) return ERR;
  381.  
  382.     for(i = 0; i < NUMMONS; i++)
  383.         if(!strncmp(s, mons[i].mname, strlen(mons[i].mname))
  384.            && (!c || class == mons[i].mlet))
  385.         return i;
  386.     return ERR;
  387. }
  388.  
  389. /*
  390.  * Find the index of an object in the table, knowing its name.
  391.  */
  392. int
  393. get_object_id(s)
  394. char *s;
  395. {
  396.     register int i;
  397.     register const char *objname;
  398.  
  399.     SpinCursor(3);
  400.     for (i=0; i<=NROFOBJECTS; i++)
  401.         if ((objname = obj_descr[i].oc_name)
  402.            && !strncmp(s, objname, strlen(objname)))
  403.         return i;
  404.     return ERR;
  405. }
  406.  
  407. /*
  408.  * Is the character 'c' a valid monster class ?
  409.  */
  410. boolean
  411. check_monster_char(c)
  412. char c;
  413. {
  414.     return (def_char_to_monclass(c) != MAXMCLASSES);
  415. }
  416.  
  417. /*
  418.  * Is the character 'c' a valid object class ?
  419.  */
  420. boolean
  421. check_object_char(c)
  422. char c;
  423. {
  424.     return (def_char_to_objclass(c) != MAXOCLASSES);
  425. }
  426.  
  427. char
  428. what_map_char(c)
  429.  
  430.      char    c;
  431. {
  432.     SpinCursor(3);
  433.     switch(c) {
  434.           case ' '  : return(STONE);
  435.           case '#'  : return(CORR);
  436.           case '.'  : return(ROOM);
  437.           case '-'  : return(HWALL);
  438.           case '|'  : return(VWALL);
  439.           case '+'  : return(DOOR);
  440.           case 'A'  : return(AIR);
  441.           case 'B'  : return(CROSSWALL); /* hack: boundary location */
  442.           case 'C'  : return(CLOUD);
  443.           case 'S'  : return(SDOOR);
  444.           case '{'  : return(FOUNTAIN);
  445.           case '\\' : return(THRONE);
  446.           case 'K'  :
  447. #ifdef SINKS
  448.               return(SINK);
  449. #else
  450.               yywarning("Sinks are not allowed in this version!  Ignoring...");
  451.               return(ROOM);
  452. #endif
  453.           case '}'  : return(MOAT);
  454.           case 'P'  : return(POOL);
  455.           case 'L'  : return(LAVAPOOL);
  456.           case 'I'  : return(ICE);
  457.           case 'W'  : return(WATER);
  458.         }
  459.     return(INVALID_TYPE);
  460. }
  461.  
  462. /*
  463.  * Yep! LEX gives us the map in a raw mode.
  464.  * Just analyze it here.
  465.  */
  466.  
  467. void
  468. scan_map(map)
  469. char *map;
  470. {
  471.     register int i, len;
  472.     register char *s1, *s2;
  473.     int max_len = 0;
  474.     int max_hig = 0;
  475.     char msg[256];
  476.  
  477.     /* First : find the max width of the map */
  478.  
  479.     s1 = map;
  480.     while (s1 && *s1) {
  481.         s2 = index(s1, NEWLINE);
  482.         if (s2) {
  483.             if (s2-s1 > max_len)
  484.                 max_len = s2-s1;
  485.             s1 = s2 + 1;
  486.         } else {
  487.             if (strlen(s1) > max_len)
  488.                 max_len = strlen(s1);
  489.             s1 = (char *) 0;
  490.         }
  491.     }
  492.  
  493.     /* Then parse it now */
  494.  
  495.     while (map && *map) {
  496.         tmpmap[max_hig] = (char *) alloc(max_len);
  497.         s1 = index(map, NEWLINE);
  498.         if (s1) {
  499.             len = s1 - map;
  500.             s1++;
  501.         } else {
  502.             len = strlen(map);
  503.             s1 = map + len;
  504.         }
  505.         for(i=0; i<len; i++)
  506.           if((tmpmap[max_hig][i] = what_map_char(map[i])) == INVALID_TYPE) {
  507.               Sprintf(msg,
  508.              "Invalid character @ (%d, %d) - replacing with stone",
  509.                   max_hig, i);
  510.               yywarning(msg);
  511.               tmpmap[max_hig][i] = STONE;
  512.             }
  513.         while(i < max_len)
  514.             tmpmap[max_hig][i++] = STONE;
  515.         map = s1;
  516.         max_hig++;
  517.     }
  518.  
  519.     /* Memorize boundaries */
  520.  
  521.     max_x_map = max_len - 1;
  522.     max_y_map = max_hig - 1;
  523.  
  524.     /* Store the map into the mazepart structure */
  525.  
  526.     if(max_len > MAP_X_LIM || max_hig > MAP_Y_LIM) {
  527.         Sprintf(msg, "Map too large! (max %d x %d)", MAP_X_LIM, MAP_Y_LIM);
  528.         yyerror(msg);
  529.     }
  530.  
  531.     tmppart[npart]->xsize = max_len;
  532.     tmppart[npart]->ysize = max_hig;
  533.     tmppart[npart]->map = (char **) alloc(max_hig*sizeof(char *));
  534.     for(i = 0; i< max_hig; i++)
  535.         tmppart[npart]->map[i] = tmpmap[i];
  536. }
  537.  
  538. /*
  539.  *    If we have drawn a map without walls, this allows us to
  540.  *    auto-magically wallify it.
  541.  */
  542. #define Map_point(x,y) *(tmppart[npart]->map[y] + x)
  543. #define Valid_point(x,y) ((x >= 0 && x <= max_x_map) && \
  544.               (y >= 0 && y <= max_y_map))
  545. void
  546. wallify_map()
  547. {
  548.  
  549.     int x, y, xx, yy;
  550.  
  551.     for(y = 0; y <= max_y_map; y++) {
  552.       SpinCursor(3);
  553.       for(x = 0; x <= max_x_map; x++)
  554.  
  555.         if(Map_point(x,y) == STONE) {
  556.  
  557.           for(yy = y - 1; yy <= y+1 && Map_point(x,y) == STONE; yy++)
  558.         for(xx = x - 1; xx <= x+1 && Map_point(x,y) == STONE; xx++)
  559.  
  560.           if(Valid_point(xx,yy) &&
  561.              (IS_ROOM(Map_point(xx,yy)) ||
  562.               Map_point(xx,yy) == CROSSWALL)) {
  563.  
  564.             if(yy != y)    Map_point(x,y) = HWALL;
  565.             else    Map_point(x,y) = VWALL;
  566.           }
  567.         }
  568.     }
  569. }
  570.  
  571. /*
  572.  * We need to check the subrooms apartenance to an existing room.
  573.  */
  574.  
  575. boolean
  576. check_subrooms()
  577. {
  578.     short i,j;
  579.     boolean found, ok = TRUE;
  580.     char msg[256];
  581.  
  582.     for (i = 0; i < nrooms; i++)
  583.         if (tmproom[i]->parent) {
  584.             found = FALSE;
  585.             for(j = 0; j < nrooms; j++)
  586.             if (tmproom[j]->name && !strcmp(tmproom[i]->parent,
  587.                             tmproom[j]->name)) {
  588.                 found = TRUE;
  589.                 break;
  590.             }
  591.             if (!found) {
  592.                 Sprintf(msg,"Subroom error : parent room '%s' not found!", tmproom[i]->parent);
  593.                 yyerror(msg);
  594.                 ok = FALSE;
  595.             }
  596.         }
  597.     return ok;
  598. }
  599.  
  600. /*
  601.  * Check that coordinates (x,y) are roomlike locations.
  602.  * Print warning "str" if they aren't.
  603.  */
  604.  
  605. void
  606. check_coord(x, y, str)
  607. int x, y;
  608. char *str;
  609. {
  610.     char ebuf[60];
  611.  
  612.     if (x >= 0 && y >= 0 && x <= max_x_map && y <= max_y_map &&
  613.     (IS_ROCK(tmpmap[y][x]) || IS_DOOR(tmpmap[y][x]))) {
  614.     Sprintf(ebuf, "%s placed in wall at (%02d,%02d)?!", str, x, y);
  615.     yywarning(ebuf);
  616.     }
  617. }
  618.  
  619. /*
  620.  * Here we want to store the maze part we just got.
  621.  */
  622.  
  623. void
  624. store_part()
  625. {
  626.     register int i;
  627.  
  628.     /* Ok, We got the whole part, now we store it. */
  629.  
  630.     /* The Regions */
  631.  
  632.     if ((tmppart[npart]->nreg = nreg) != 0) {
  633.         tmppart[npart]->regions = NewTab(region, nreg);
  634.         for(i=0;i<nreg;i++)
  635.             tmppart[npart]->regions[i] = tmpreg[i];
  636.     }
  637.     nreg = 0;
  638.  
  639.     /* The Level Regions */
  640.  
  641.     if ((tmppart[npart]->nlreg = nlreg) != 0) {
  642.         tmppart[npart]->lregions = NewTab(lev_region, nlreg);
  643.         for(i=0;i<nlreg;i++)
  644.             tmppart[npart]->lregions[i] = tmplreg[i];
  645.     }
  646.     nlreg = 0;
  647.  
  648.     /* the doors */
  649.  
  650.     if ((tmppart[npart]->ndoor = ndoor) != 0) {
  651.         tmppart[npart]->doors = NewTab(door, ndoor);
  652.         for(i=0;i<ndoor;i++)
  653.             tmppart[npart]->doors[i] = tmpdoor[i];
  654.     }
  655.     ndoor = 0;
  656.  
  657.     /* the traps */
  658.  
  659.     if ((tmppart[npart]->ntrap = ntrap) != 0) {
  660.         tmppart[npart]->traps = NewTab(trap, ntrap);
  661.         for(i=0;i<ntrap;i++)
  662.             tmppart[npart]->traps[i] = tmptrap[i];
  663.     }
  664.     ntrap = 0;
  665.  
  666.     /* the monsters */
  667.  
  668.     if ((tmppart[npart]->nmonster = nmons) != 0) {
  669.         tmppart[npart]->monsters = NewTab(monster, nmons);
  670.         for(i=0;i<nmons;i++)
  671.             tmppart[npart]->monsters[i] = tmpmonst[i];
  672.     }
  673.     nmons = 0;
  674.  
  675.     /* the objects */
  676.  
  677.     if ((tmppart[npart]->nobject = nobj) != 0) {
  678.         tmppart[npart]->objects = NewTab(object, nobj);
  679.         for(i=0;i<nobj;i++)
  680.             tmppart[npart]->objects[i] = tmpobj[i];
  681.     }
  682.     nobj = 0;
  683.  
  684.     /* the drawbridges */
  685.  
  686.     if ((tmppart[npart]->ndrawbridge = ndb) != 0) {
  687.         tmppart[npart]->drawbridges = NewTab(drawbridge, ndb);
  688.         for(i=0;i<ndb;i++)
  689.             tmppart[npart]->drawbridges[i] = tmpdb[i];
  690.     }
  691.     ndb = 0;
  692.  
  693.     /* The walkmaze directives */
  694.  
  695.     if ((tmppart[npart]->nwalk = nwalk) != 0) {
  696.         tmppart[npart]->walks = NewTab(walk, nwalk);
  697.         for(i=0;i<nwalk;i++)
  698.             tmppart[npart]->walks[i] = tmpwalk[i];
  699.     }
  700.     nwalk = 0;
  701.  
  702.     /* The non_diggable directives */
  703.  
  704.     if ((tmppart[npart]->ndig = ndig) != 0) {
  705.         tmppart[npart]->digs = NewTab(digpos, ndig);
  706.         for(i=0;i<ndig;i++)
  707.             tmppart[npart]->digs[i] = tmpdig[i];
  708.     }
  709.     ndig = 0;
  710.  
  711.     /* The ladders */
  712.  
  713.     if ((tmppart[npart]->nlad = nlad) != 0) {
  714.         tmppart[npart]->lads = NewTab(lad, nlad);
  715.         for(i=0;i<nlad;i++)
  716.             tmppart[npart]->lads[i] = tmplad[i];
  717.     }
  718.     nlad = 0;
  719.  
  720.     /* The stairs */
  721.  
  722.     if ((tmppart[npart]->nstair = nstair) != 0) {
  723.         tmppart[npart]->stairs = NewTab(stair, nstair);
  724.         for(i=0;i<nstair;i++)
  725.             tmppart[npart]->stairs[i] = tmpstair[i];
  726.     }
  727.     nstair = 0;
  728.  
  729.     /* The altars */
  730.     if ((tmppart[npart]->naltar = naltar) != 0) {
  731.         tmppart[npart]->altars = NewTab(altar, naltar);
  732.         for(i=0;i<naltar;i++)
  733.             tmppart[npart]->altars[i] = tmpaltar[i];
  734.     }
  735.     naltar = 0;
  736.  
  737.     /* The gold piles */
  738.  
  739.     if ((tmppart[npart]->ngold = ngold) != 0) {
  740.         tmppart[npart]->golds = NewTab(gold, ngold);
  741.         for(i=0;i<ngold;i++)
  742.             tmppart[npart]->golds[i] = tmpgold[i];
  743.     }
  744.     ngold = 0;
  745.  
  746.     /* The engravings */
  747.  
  748.     if ((tmppart[npart]->nengraving = nengraving) != 0) {
  749.         tmppart[npart]->engravings = NewTab(engraving, nengraving);
  750.         for(i=0;i<nengraving;i++)
  751.             tmppart[npart]->engravings[i] = tmpengraving[i];
  752.     }
  753.     nengraving = 0;
  754.  
  755.     /* The fountains */
  756.  
  757.     if ((tmppart[npart]->nfountain = nfountain) != 0) {
  758.         tmppart[npart]->fountains = NewTab(fountain, nfountain);
  759.         for(i=0;i<nfountain;i++)
  760.             tmppart[npart]->fountains[i] = tmpfountain[i];
  761.     }
  762.     nfountain = 0;
  763.  
  764.     npart++;
  765.     n_plist = n_mlist = n_olist = 0;
  766. }
  767.  
  768. /*
  769.  * Here we want to store the room part we just got.
  770.  */
  771.  
  772. void
  773. store_room()
  774. {
  775.     register int i;
  776.  
  777.     /* Ok, We got the whole room, now we store it. */
  778.  
  779.     /* the doors */
  780.  
  781.     if ((tmproom[nrooms]->ndoor = ndoor) != 0) {
  782.         tmproom[nrooms]->doors = NewTab(room_door, ndoor);
  783.         for(i=0;i<ndoor;i++)
  784.             tmproom[nrooms]->doors[i] = tmprdoor[i];
  785.     }
  786.     ndoor = 0;
  787.  
  788.     /* the traps */
  789.  
  790.     if ((tmproom[nrooms]->ntrap = ntrap) != 0) {
  791.         tmproom[nrooms]->traps = NewTab(trap, ntrap);
  792.         for(i=0;i<ntrap;i++)
  793.             tmproom[nrooms]->traps[i] = tmptrap[i];
  794.     }
  795.     ntrap = 0;
  796.  
  797.     /* the monsters */
  798.  
  799.     if ((tmproom[nrooms]->nmonster = nmons) != 0) {
  800.         tmproom[nrooms]->monsters = NewTab(monster, nmons);
  801.         for(i=0;i<nmons;i++)
  802.             tmproom[nrooms]->monsters[i] = tmpmonst[i];
  803.     }
  804.     nmons = 0;
  805.  
  806.     /* the objects */
  807.  
  808.     if ((tmproom[nrooms]->nobject = nobj) != 0) {
  809.         tmproom[nrooms]->objects = NewTab(object, nobj);
  810.         for(i=0;i<nobj;i++)
  811.             tmproom[nrooms]->objects[i] = tmpobj[i];
  812.     }
  813.     nobj = 0;
  814.  
  815.     /* The stairs */
  816.  
  817.     if ((tmproom[nrooms]->nstair = nstair) != 0) {
  818.         tmproom[nrooms]->stairs = NewTab(stair, nstair);
  819.         for(i=0;i<nstair;i++)
  820.             tmproom[nrooms]->stairs[i] = tmpstair[i];
  821.     }
  822.     nstair = 0;
  823.  
  824.     /* The altars */
  825.     if ((tmproom[nrooms]->naltar = naltar) != 0) {
  826.         tmproom[nrooms]->altars = NewTab(altar, naltar);
  827.         for(i=0;i<naltar;i++)
  828.             tmproom[nrooms]->altars[i] = tmpaltar[i];
  829.     }
  830.     naltar = 0;
  831.  
  832.     /* The gold piles */
  833.  
  834.     if ((tmproom[nrooms]->ngold = ngold) != 0) {
  835.         tmproom[nrooms]->golds = NewTab(gold, ngold);
  836.         for(i=0;i<ngold;i++)
  837.             tmproom[nrooms]->golds[i] = tmpgold[i];
  838.     }
  839.     ngold = 0;
  840.  
  841.     /* The engravings */
  842.  
  843.     if ((tmproom[nrooms]->nengraving = nengraving) != 0) {
  844.         tmproom[nrooms]->engravings = NewTab(engraving, nengraving);
  845.         for(i=0;i<nengraving;i++)
  846.             tmproom[nrooms]->engravings[i] = tmpengraving[i];
  847.     }
  848.     nengraving = 0;
  849.  
  850.     /* The fountains */
  851.  
  852.     if ((tmproom[nrooms]->nfountain = nfountain) != 0) {
  853.         tmproom[nrooms]->fountains = NewTab(fountain, nfountain);
  854.         for(i=0;i<nfountain;i++)
  855.             tmproom[nrooms]->fountains[i] = tmpfountain[i];
  856.     }
  857.     nfountain = 0;
  858.  
  859.     /* The sinks */
  860.  
  861.     if ((tmproom[nrooms]->nsink = nsink) != 0) {
  862.         tmproom[nrooms]->sinks = NewTab(sink, nsink);
  863.         for(i=0;i<nsink;i++)
  864.             tmproom[nrooms]->sinks[i] = tmpsink[i];
  865.     }
  866.     nsink = 0;
  867.  
  868.     /* The pools */
  869.  
  870.     if ((tmproom[nrooms]->npool = npool) != 0) {
  871.         tmproom[nrooms]->pools = NewTab(pool, npool);
  872.         for(i=0;i<npool;i++)
  873.             tmproom[nrooms]->pools[i] = tmppool[i];
  874.     }
  875.     npool = 0;
  876.  
  877.     nrooms++;
  878. }
  879.  
  880. /* some info common to all special levels */
  881. static void
  882. write_common_data(fd, typ, init, flgs)
  883. int fd, typ;
  884. lev_init *init;
  885. long flgs;
  886. {
  887.     char c;
  888.     uchar len;
  889.  
  890.     c = typ;
  891.     Write(fd, &c, sizeof(c));    /* 1 byte header */
  892.     Write(fd, init, sizeof(lev_init));
  893.     Write(fd, &flgs, sizeof flgs);
  894.  
  895.     len = strlen(tmpmessage);
  896.     Write(fd, &len, sizeof len);
  897.     if (len) Write(fd, tmpmessage, (int) len);
  898.     tmpmessage[0] = '\0';
  899. }
  900.  
  901. /*
  902.  * Here we write the structure of the maze in the specified file (fd).
  903.  * Also, we have to free the memory allocated via alloc()
  904.  */
  905.  
  906. void
  907. write_maze(fd, maze)
  908. int fd;
  909. specialmaze *maze;
  910. {
  911.     short i,j;
  912.     mazepart *pt;
  913.  
  914.     write_common_data(fd, SP_LEV_MAZE, &(maze->init_lev), maze->flags);
  915.  
  916.     Write(fd, &(maze->filling), sizeof(maze->filling));
  917.     Write(fd, &(maze->numpart), sizeof(maze->numpart));
  918.                      /* Number of parts */
  919.     for(i=0;i<maze->numpart;i++) {
  920.         pt = maze->parts[i];
  921.  
  922.         /* First, write the map */
  923.  
  924.         Write(fd, &(pt->halign), sizeof(pt->halign));
  925.         Write(fd, &(pt->valign), sizeof(pt->valign));
  926.         Write(fd, &(pt->xsize), sizeof(pt->xsize));
  927.         Write(fd, &(pt->ysize), sizeof(pt->ysize));
  928.         for(j=0;j<pt->ysize;j++) {
  929.         if(!maze->init_lev.init_present ||
  930.            pt->xsize > 1 || pt->ysize > 1)
  931.             Write(fd, pt->map[j], sizeof(*(pt->map[j])) * pt->xsize);
  932.         Free(pt->map[j]);
  933.         }
  934.         Free(pt->map);
  935.  
  936.         /* level region stuff */
  937.         Write(fd, &(pt->nlreg), sizeof(pt->nlreg));
  938.         for(j=0;j<pt->nlreg;j++) {
  939.             Write(fd, pt->lregions[j], sizeof(lev_region));
  940.             if(pt->lregions[j]->rname) {
  941.                 char c = strlen(pt->lregions[j]->rname);
  942.                 Write(fd, &c, sizeof(c));
  943.                 Write(fd, pt->lregions[j]->rname, (int)c);
  944.             }
  945.             Free(pt->lregions[j]);
  946.         }
  947.         if(pt->nlreg > 0)
  948.             Free(pt->lregions);
  949.  
  950.         /* The random registers */
  951.         Write(fd, &(pt->nrobjects), sizeof(pt->nrobjects));
  952.         if(pt->nrobjects) {
  953.             Write(fd, pt->robjects, pt->nrobjects);
  954.             Free(pt->robjects);
  955.         }
  956.         Write(fd, &(pt->nloc), sizeof(pt->nloc));
  957.         if(pt->nloc) {
  958.             Write(fd, pt->rloc_x, pt->nloc);
  959.             Write(fd, pt->rloc_y, pt->nloc);
  960.             Free(pt->rloc_x);
  961.             Free(pt->rloc_y);
  962.         }
  963.         Write(fd, &(pt->nrmonst), sizeof(pt->nrmonst));
  964.         if(pt->nrmonst) {
  965.             Write(fd, pt->rmonst, pt->nrmonst);
  966.             Free(pt->rmonst);
  967.         }
  968.  
  969.         /* subrooms */
  970.         Write(fd, &(pt->nreg), sizeof(pt->nreg));
  971.         for(j=0;j<pt->nreg;j++) {
  972.             Write(fd, pt->regions[j], sizeof(region));
  973.             Free(pt->regions[j]);
  974.         }
  975.         if(pt->nreg > 0)
  976.             Free(pt->regions);
  977.  
  978.         /* the doors */
  979.         Write(fd, &(pt->ndoor), sizeof(pt->ndoor));
  980.         for(j=0;j<pt->ndoor;j++) {
  981.             Write(fd, pt->doors[j], sizeof(door));
  982.             Free(pt->doors[j]);
  983.         }
  984.         if (pt->ndoor > 0)
  985.             Free(pt->doors);
  986.  
  987.         /* The traps */
  988.         Write(fd, &(pt->ntrap), sizeof(pt->ntrap));
  989.         for(j=0;j<pt->ntrap;j++) {
  990.             Write(fd, pt->traps[j], sizeof(trap));
  991.             Free(pt->traps[j]);
  992.         }
  993.         if (pt->ntrap)
  994.             Free(pt->traps);
  995.  
  996.         /* The monsters */
  997.         Write(fd, &(pt->nmonster), sizeof(pt->nmonster));
  998.         for(j=0;j<pt->nmonster;j++) {
  999.             short size;
  1000.             monster *m = pt->monsters[j];
  1001.             Write(fd, m, sizeof(monster));
  1002.             size = m->name ? strlen(m->name) : 0;
  1003.             Write(fd, &size, sizeof(size));
  1004.             if (size) {
  1005.                 Write(fd, m->name, size);
  1006.                 Free(m->name);
  1007.             }
  1008.             size = m->appear_as ? strlen(m->appear_as) : 0;
  1009.             Write(fd, &size, sizeof(size));
  1010.             if (size) {
  1011.                 Write(fd, m->appear_as, size);
  1012.                 Free(m->appear_as);
  1013.             }
  1014.             Free(pt->monsters[j]);
  1015.         }
  1016.         if (pt->nmonster > 0)
  1017.             Free(pt->monsters);
  1018.  
  1019.         /* The objects */
  1020.         Write(fd, &(pt->nobject), sizeof(pt->nobject));
  1021.         for(j=0;j<pt->nobject;j++) {
  1022.             short size;
  1023.             object *o = pt->objects[j];
  1024.             Write(fd, o, sizeof(object));
  1025.             size = o->name ? strlen(o->name) : 0;
  1026.             Write(fd, &size, sizeof(size));
  1027.             if (size) {
  1028.                 Write(fd, o->name, size);
  1029.                 Free(o->name);
  1030.             }
  1031.             Free(pt->objects[j]);
  1032.         }
  1033.         if(pt->nobject > 0)
  1034.             Free(pt->objects);
  1035.  
  1036.         /* The drawbridges */
  1037.         Write(fd, &(pt->ndrawbridge), sizeof(pt->ndrawbridge));
  1038.         for(j=0;j<pt->ndrawbridge;j++) {
  1039.             Write(fd, pt->drawbridges[j], sizeof(drawbridge));
  1040.             Free(pt->drawbridges[j]);
  1041.         }
  1042.         if(pt->ndrawbridge > 0)
  1043.             Free(pt->drawbridges);
  1044.  
  1045.         /* The mazewalk directives */
  1046.         Write(fd, &(pt->nwalk), sizeof(pt->nwalk));
  1047.         for(j=0; j<pt->nwalk; j++) {
  1048.             Write(fd, pt->walks[j], sizeof(walk));
  1049.             Free(pt->walks[j]);
  1050.         }
  1051.         if (pt->nwalk > 0)
  1052.             Free(pt->walks);
  1053.  
  1054.         /* The non_diggable directives */
  1055.         Write(fd, &(pt->ndig), sizeof(pt->ndig));
  1056.         for(j=0;j<pt->ndig;j++) {
  1057.             Write(fd, pt->digs[j], sizeof(digpos));
  1058.             Free(pt->digs[j]);
  1059.         }
  1060.         if (pt->ndig > 0)
  1061.             Free(pt->digs);
  1062.  
  1063.         /* The ladders */
  1064.         Write(fd, &(pt->nlad), sizeof(pt->nlad));
  1065.         for(j=0;j<pt->nlad;j++) {
  1066.             Write(fd, pt->lads[j], sizeof(lad));
  1067.             Free(pt->lads[j]);
  1068.         }
  1069.         if (pt->nlad > 0)
  1070.             Free(pt->lads);
  1071.  
  1072.         /* The stairs */
  1073.         Write(fd, &(pt->nstair), sizeof(pt->nstair));
  1074.         for(j=0;j<pt->nstair;j++) {
  1075.             Write(fd, pt->stairs[j], sizeof(stair));
  1076.             Free(pt->stairs[j]);
  1077.         }
  1078.         if (pt->nstair > 0)
  1079.             Free(pt->stairs);
  1080.  
  1081.         /* The altars */
  1082.         Write(fd, &(pt->naltar), sizeof(pt->naltar));
  1083.         for(j=0;j<pt->naltar;j++) {
  1084.             Write(fd, pt->altars[j], sizeof(altar));
  1085.             Free(pt->altars[j]);
  1086.         }
  1087.         if (pt->naltar > 0)
  1088.             Free(pt->altars);
  1089.  
  1090.         /* The gold piles */
  1091.         Write(fd, &(pt->ngold), sizeof(pt->naltar));
  1092.         for(j=0;j<pt->ngold;j++) {
  1093.             Write(fd, pt->golds[j], sizeof(gold));
  1094.             Free(pt->golds[j]);
  1095.         }
  1096.         if (pt->ngold > 0)
  1097.             Free(pt->golds);
  1098.  
  1099.         /* The engravings */
  1100.         Write(fd, &(pt->nengraving), sizeof(pt->nengraving));
  1101.         for(j=0;j<pt->nengraving;j++) {
  1102.             char *txt;
  1103.             int size;
  1104.             txt = pt->engravings[j]->e.text;
  1105.             size = pt->engravings[j]->e.length = strlen(txt);
  1106.             Write(fd, pt->engravings[j], sizeof *pt->engravings[j]);
  1107.             Write(fd, txt, size);
  1108.             Free(txt);
  1109.             Free(pt->engravings[j]);
  1110.         }
  1111.         if (pt->nengraving > 0)
  1112.             Free(pt->engravings);
  1113.  
  1114.         /* The fountains */
  1115.         Write(fd, &(pt->nfountain), sizeof(pt->nfountain));
  1116.         for(j=0;j<pt->nfountain;j++) {
  1117.         Write(fd, pt->fountains[j], sizeof(fountain));
  1118.         Free(pt->fountains[j]);
  1119.         }
  1120.         if (pt->nfountain > 0)
  1121.             Free(pt->fountains);
  1122.  
  1123.         Free(pt);
  1124.     }
  1125. }
  1126.  
  1127. /*
  1128.  * Here we write the structure of the room level in the specified file (fd).
  1129.  */
  1130.  
  1131. void
  1132. write_lev(fd, lev)
  1133. int fd;
  1134. splev *lev;
  1135. {
  1136.     short i,j, size;
  1137.     room *pt;
  1138.  
  1139.     write_common_data(fd, SP_LEV_ROOMS, &(lev->init_lev), lev->flags);
  1140.  
  1141.     /* Random registers */
  1142.  
  1143.     Write(fd, &lev->nrobjects, sizeof(lev->nrobjects));
  1144.     if (lev->nrobjects) {
  1145.         Write(fd, lev->robjects, lev->nrobjects);
  1146.         Free (lev->robjects);
  1147.     }
  1148.     Write(fd, &lev->nrmonst, sizeof(lev->nrmonst));
  1149.     if (lev->nrmonst) {
  1150.         Write(fd, lev->rmonst, lev->nrmonst);
  1151.         Free (lev->rmonst);
  1152.     }
  1153.  
  1154.     Write(fd, &(lev->nroom), sizeof(lev->nroom));
  1155.                             /* Number of rooms */
  1156.     for(i=0;i<lev->nroom;i++) {
  1157.         pt = lev->rooms[i];
  1158.  
  1159.         /* Room characteristics */
  1160.  
  1161.         if (pt->name)
  1162.             size = strlen(pt->name);
  1163.         else
  1164.             size = 0;
  1165.         Write(fd, &size, sizeof(size));
  1166.         if (size)
  1167.             Write(fd, pt->name, size);
  1168.  
  1169.         if (pt->parent)
  1170.             size = strlen(pt->parent);
  1171.         else
  1172.             size = 0;
  1173.         Write(fd, &size, sizeof(size));
  1174.         if (size)
  1175.             Write(fd, pt->parent, size);
  1176.  
  1177.         Write(fd, &(pt->x), sizeof(pt->x));
  1178.         Write(fd, &(pt->y), sizeof(pt->y));
  1179.         Write(fd, &(pt->w), sizeof(pt->w));
  1180.         Write(fd, &(pt->h), sizeof(pt->h));
  1181.         Write(fd, &(pt->xalign), sizeof(pt->xalign));
  1182.         Write(fd, &(pt->yalign), sizeof(pt->yalign));
  1183.         Write(fd, &(pt->rtype), sizeof(pt->rtype));
  1184.         Write(fd, &(pt->chance), sizeof(pt->chance));
  1185.         Write(fd, &(pt->rlit), sizeof(pt->rlit));
  1186.         Write(fd, &(pt->filled), sizeof(pt->filled));
  1187.  
  1188.         /* the doors */
  1189.         Write(fd, &(pt->ndoor), sizeof(pt->ndoor));
  1190.         for(j=0;j<pt->ndoor;j++)
  1191.             Write(fd, pt->doors[j], sizeof(room_door));
  1192.         /* The traps */
  1193.         Write(fd, &(pt->ntrap), sizeof(pt->ntrap));
  1194.         for(j=0;j<pt->ntrap;j++)
  1195.             Write(fd, pt->traps[j], sizeof(trap));
  1196.  
  1197.         /* The monsters */
  1198.         Write(fd, &(pt->nmonster), sizeof(pt->nmonster));
  1199.         for(j=0;j<pt->nmonster;j++) {
  1200.             monster *m = pt->monsters[j];
  1201.             Write(fd, m, sizeof(monster));
  1202.             size = m->name ? strlen(m->name) : 0;
  1203.             Write(fd, &size, sizeof(size));
  1204.             if (size)
  1205.                 Write(fd, m->name, size);
  1206.             size = m->appear_as ? strlen(m->appear_as) : 0;
  1207.             Write(fd, &size, sizeof(size));
  1208.             if (size)
  1209.                 Write(fd, m->appear_as, size);
  1210.         }
  1211.  
  1212.         /* The objects */
  1213.         Write(fd, &(pt->nobject), sizeof(pt->nobject));
  1214.         for(j=0;j<pt->nobject;j++) {
  1215.             object *o = pt->objects[j];
  1216.             Write(fd, o, sizeof(object));
  1217.             size = o->name ? strlen(o->name) : 0;
  1218.             Write(fd, &size, sizeof(size));
  1219.             if (size)
  1220.                 Write(fd,  o->name, size);
  1221.         }
  1222.  
  1223.         /* The stairs */
  1224.         Write(fd, &(pt->nstair), sizeof(pt->nstair));
  1225.         for(j=0;j<pt->nstair;j++)
  1226.             Write(fd, pt->stairs[j], sizeof(stair));
  1227.  
  1228.         /* The altars */
  1229.         Write(fd, &(pt->naltar), sizeof(pt->naltar));
  1230.         for(j=0;j<pt->naltar;j++)
  1231.             Write(fd, pt->altars[j], sizeof(altar));
  1232.  
  1233.         /* The gold piles */
  1234.         Write(fd, &(pt->ngold), sizeof(pt->ngold));
  1235.         for(j=0;j<pt->ngold;j++)
  1236.             Write(fd, pt->golds[j], sizeof(gold));
  1237.  
  1238.         /* The engravings */
  1239.         Write(fd, &(pt->nengraving), sizeof(pt->nengraving));
  1240.         for(j=0;j<pt->nengraving;j++) {
  1241.             char *txt;
  1242.             txt = pt->engravings[j]->e.text;
  1243.             size = pt->engravings[j]->e.length = strlen(txt);
  1244.             Write(fd, pt->engravings[j],
  1245.                   sizeof *pt->engravings[j]);
  1246.             Write(fd, txt, size);
  1247.         }
  1248.  
  1249.         /* The fountains */
  1250.         Write(fd, &(pt->nfountain), sizeof(pt->nfountain));
  1251.         for(j=0;j<pt->nfountain;j++)
  1252.             Write(fd, pt->fountains[j], sizeof(fountain));
  1253.  
  1254.         /* The sinks */
  1255.         Write(fd, &(pt->nsink), sizeof(pt->nsink));
  1256.         for(j=0;j<pt->nsink;j++)
  1257.             Write(fd, pt->sinks[j], sizeof(sink));
  1258.  
  1259.         /* The pools */
  1260.         Write(fd, &(pt->npool), sizeof(pt->npool));
  1261.         for(j=0;j<pt->npool;j++)
  1262.             Write(fd, pt->pools[j], sizeof(pool));
  1263.     }
  1264.  
  1265.     /* The corridors */
  1266.     Write(fd, &ncorridor, sizeof(ncorridor));
  1267.     for (i=0; i<ncorridor; i++) {
  1268.         Write(fd, tmpcor[i], sizeof(corridor));
  1269.         Free(tmpcor[i]);
  1270.     }
  1271.     ncorridor = 0;
  1272. }
  1273.  
  1274. void
  1275. free_rooms(ro, n)
  1276. room **ro;
  1277. int n;
  1278. {
  1279.     short j;
  1280.     room *r;
  1281.  
  1282.     while(n--) {
  1283.         r = ro[n];
  1284.         Free(r->name);
  1285.         Free(r->parent);
  1286.         if ((j = r->ndoor) != 0) {
  1287.             while(j--)
  1288.                 Free(r->doors[j]);
  1289.             Free(r->doors);
  1290.         }
  1291.         if ((j = r->ntrap) != 0) {
  1292.             while (j--)
  1293.                 Free(r->traps[j]);
  1294.             Free(r->traps);
  1295.         }
  1296.         if ((j = r->nmonster) != 0) {
  1297.             while (j--) {
  1298.                 Free(r->monsters[j]->name);
  1299.                 Free(r->monsters[j]->appear_as);
  1300.                 Free(r->monsters[j]);
  1301.             }
  1302.             Free(r->monsters);
  1303.         }
  1304.         if ((j = r->nobject) != 0) {
  1305.             while(j--) {
  1306.                 Free(r->objects[j]->name);
  1307.                 Free(r->objects[j]);
  1308.             }
  1309.             Free(r->objects);
  1310.         }
  1311.         if ((j = r->nstair) != 0) {
  1312.             while(j--)
  1313.                 Free(r->stairs[j]);
  1314.             Free(r->stairs);
  1315.         }
  1316.         if ((j = r->naltar) != 0) {
  1317.             while (j--)
  1318.                 Free(r->altars[j]);
  1319.             Free(r->altars);
  1320.         }
  1321.         if ((j = r->ngold) != 0) {
  1322.             while(j--)
  1323.                 Free(r->golds[j]);
  1324.             Free(r->golds);
  1325.         }
  1326.         if ((j = r->nengraving) != 0) {
  1327.             while(j--) {
  1328.                 Free(r->engravings[j]->e.text);
  1329.                 Free(r->engravings[j]);
  1330.             }
  1331.             Free(r->engravings);
  1332.         }
  1333.         if ((j = r->nfountain) != 0) {
  1334.             while(j--)
  1335.                 Free(r->fountains[j]);
  1336.             Free(r->fountains);
  1337.         }
  1338.         if ((j = r->nsink) != 0) {
  1339.             while(j--)
  1340.                 Free(r->sinks[j]);
  1341.             Free(r->sinks);
  1342.         }
  1343.         if ((j = r->npool) != 0) {
  1344.             while(j--)
  1345.                 Free(r->pools[j]);
  1346.             Free(r->pools);
  1347.         }
  1348.         Free(r);
  1349.     }
  1350. }
  1351.  
  1352. #ifdef STRICT_REF_DEF
  1353. /*
  1354.  * Any globals declared in hack.h and descendents which aren't defined
  1355.  * in the modules linked into lev_comp should be defined here.  These
  1356.  * definitions can be dummies:  their sizes shouldn't matter as long as
  1357.  * as their types are correct; actual values are irrelevant.
  1358.  */
  1359. #define ARBITRARY_SIZE 1
  1360. /* attrib.c */
  1361. struct attribs attrmax, attrmin;
  1362. /* files.c */
  1363. const char *configfile;
  1364. char lock[ARBITRARY_SIZE];
  1365. char SAVEF[ARBITRARY_SIZE];
  1366. # ifdef MICRO
  1367. char SAVEP[ARBITRARY_SIZE];
  1368. # endif
  1369. /* termcap.c */
  1370. struct tc_lcl_data tc_lcl_data;
  1371. # ifdef TEXTCOLOR
  1372. #  ifdef TOS
  1373. const char *hilites[MAXCOLORS];
  1374. #  else
  1375. char NEARDATA *hilites[MAXCOLORS];
  1376. #  endif
  1377. # endif
  1378. /* trap.c */
  1379. const char *traps[TRAPNUM];
  1380. /* window.c */
  1381. struct window_procs windowprocs;
  1382. /* xxxtty.c */
  1383. # ifdef DEFINE_OSPEED
  1384. short ospeed;
  1385. # endif
  1386. #endif    /* STRICT_REF_DEF */
  1387.  
  1388. /*lev_main.c*/
  1389.